package com.wmd.core.operation;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.apache.poi.ss.usermodel.CellType.BLANK;

/**
 * 类说明
 * 
 * @author yincheng lu
 * @time 2019年3月12日上午9:34:14
 * @Description
 */
public class ExcelOperation {
	/*
	 * private List<Map> data;// 列键值对 private List<String> title;
	 */
	private String[][] allData;
	private List<CellStyle> cellStyles;
	private List<RowStyle> rowStyles;
	private String sheetName;
	private List<MergedRegion> mergedRegions;
	private List<Picture> pictures;

	public static ExcelOperation CreateExcelOperation(String[][] allData, String sheetName) {
		return new ExcelOperation(allData, sheetName);
	}

	public Workbook excel(){
		return ExportExcelFile.excel(this);
	}

	public boolean toFile(String filepath){
		return ExportExcelFile.toFile(filepath,ExportExcelFile.excel(this));
	}
	public boolean toFile(File file){
		return ExportExcelFile.toFile(file,ExportExcelFile.excel(this));
	}

	public ExcelOperation(String[][] allData, String sheetName) {
		// TODO Auto-generated constructor stub
		this.allData = allData;
		this.sheetName = sheetName;
		cellStyles = new ArrayList<>();
		rowStyles = new ArrayList<>();
		mergedRegions=new ArrayList<>();
		pictures=new ArrayList<>();
	}

	public List<Picture> getPictures() {
		return pictures;
	}

	public List<MergedRegion> getMergedRegions() {
		return mergedRegions;
	}

	public String[][] getAllData() {
		return allData;
	}


	public List<CellStyle> getCellStyles() {
		return cellStyles;
	}

	public List<RowStyle> getRowStyles() {
		return rowStyles;
	}

	public String getSheetName() {
		return sheetName;
	}

	public void setSheetName(String sheetName) {
		this.sheetName = sheetName;
	}

	public static <K, T> String[][] ObjectmapDataToStringArray(List<Map<K, T>> data, List<String> title,
			List<String> sortkey) {
		if (data.isEmpty() || sortkey.isEmpty()) {
			return null;
		}
		int rows = data.get(0).size() + 1;
		rows = rows > sortkey.size() + 1 ? rows : sortkey.size() + 1;
		int columns = title.size();
		String[][] allDatas = new String[rows][columns];
		allDatas[0] = (String[]) title.toArray(allDatas[0]);
		for (int j = 0; j < data.size(); j++) {
			Map<K, T> dataline = data.get(j);
			String[] lineData = new String[columns];
			for (int i = 0; i < sortkey.size(); i++) {
				Object o = dataline.get(sortkey.get(i));
				lineData[i] = (String) (o != null ? o + "" : "");
			}
			allDatas[j + 1] = lineData;
		}
		return allDatas;
	}

	public static String[][] mapDataToStringArray(List<Map> data, List<String> title, List<String> sortkey) {
		if (data.isEmpty() || sortkey.isEmpty()) {
			return null;
		}
		int rows = data.get(0).size() + 1;
		int columns = title.size();
		String[][] allDatas = new String[rows][columns];
		allDatas[0] = title.toArray(allDatas[0]);
		for (int i = 0; i < sortkey.size(); i++) {
			String[] lineData = new String[columns];
			for (int j = 0; j < data.size(); j++) {
				lineData[j] = (String) (data.get(j).get(sortkey.get(i)) + "");
			}
			allDatas[i + 1] = lineData;
		}
		return allDatas;
	}

	public static String[][] mapDataToStringArray(List<Map> data, List<String> title, List<String> totalTitle,
			List<String> secondTitle, List<String> sortkey) {
		if (data.isEmpty() || sortkey.isEmpty()) {
			return null;
		}
		int rows = data.size() + 3;
		int columns = title.size();
		String[][] allDatas = new String[rows][columns];
		allDatas[0] =  totalTitle.toArray(allDatas[0]);
		allDatas[1] =  secondTitle.toArray(allDatas[1]);
		allDatas[2] =title.toArray(allDatas[2]);
		for (int j = 0; j < data.size(); j++) {
			String[] lineData = new String[columns];
			for (int i = 0; i < sortkey.size(); i++) {
				if (null == data.get(j).get(sortkey.get(i))) {
					lineData[i] = "";
				} else {
					lineData[i] = (String) (data.get(j).get(sortkey.get(i)) + "");
				}

			}
			allDatas[j + 3] = lineData;
		}

		return allDatas;
	}

	public ExcelOperation addCellStyle(CellStyle cellStyle){
		cellStyles.add(cellStyle);
		return this;
	}

	public ExcelOperation addRowStyle(int rowIndex, CellStyle cellStyle) {
		if (rowIndex < 0) {
			rowIndex = cellStyle.rowIndex;
		}
		RowStyle r = new RowStyle(rowIndex, cellStyle);
		rowStyles.add(r);
		return this;
	}

	public ExcelOperation addRowStyle(int rowIndex, int rowEndIndex, CellStyle cellStyle) {
		if (rowIndex < 0) {
			rowIndex = cellStyle.rowIndex;
		}
		RowStyle r = new RowStyle(rowIndex, rowEndIndex, cellStyle);
		rowStyles.add(r);
		return this;
	}
	public static CellStyle createCellStyle(int rowIndex,int columnIndex) {
		CellStyle cellStyle= new CellStyle();
		cellStyle.setlocation(rowIndex,columnIndex);
		return cellStyle;
	}
	public static CellStyle createCellStyleForRow() {
		return new CellStyle();
	}

	public ExcelOperation addMergedRegion(int rowindex, int endRowIndex, int columnInde, int endColumnIndex){
		MergedRegion mergedRegion=new MergedRegion(rowindex,endRowIndex,columnInde,endColumnIndex);
		this.mergedRegions.add(mergedRegion);
		return this;
	}

	public ExcelOperation addPicture(int rowindex, int endRowIndex, int columnIndex, int endColumnIndex,byte[] data){
		Picture picture=new Picture(rowindex,endRowIndex,columnIndex,endColumnIndex,data);
		this.pictures.add(picture);
		return this;
	}

	public enum StyleType {
		BORDER, ALIGNMENT, FONT, FILL_COLOR, COLUMN_WIDTH
	}

	public static class RowStyle {
		private int rowIndex;
		private Integer rowEndIndex;
		private CellStyle cellStyle;
		private boolean isMuti;

		RowStyle(int rowIndex, CellStyle cellStyle) {
			this.rowIndex = rowIndex;
			this.cellStyle = cellStyle;
			isMuti = false;
		}

		RowStyle(int rowIndex, int rowEndIndex, CellStyle cellStyle) {
			this.rowIndex = rowIndex;
			this.rowEndIndex = rowEndIndex;
			this.cellStyle = cellStyle;
			if (rowEndIndex > rowIndex) {
				isMuti = true;
			}
		}

		public Integer getRowIndex() {
			return rowIndex;
		}

//		public void setRowIndex(Integer rowIndex) {
//			this.rowIndex = rowIndex;
//		}

		public CellStyle getCellStyle() {
			return cellStyle;
		}

//		public void setCellStyle(CellStyle cellStyle) {
//			this.cellStyle = cellStyle;
//		}

		public int getRowEndIndex() {
			return rowEndIndex;
		}

//		public void setRowEndIndex(int rowEndIndex) {
//			this.rowEndIndex = rowEndIndex;
//		}

		public boolean isMuti() {
			return isMuti;
		}

//		public void setMuti(boolean isMuti) {
//			this.isMuti = isMuti;
//		}

	}
	public static class MergedRegion{
		public int rowIndex;
		public int columnIndex;
		public int endRowIndex;
		public int endColumnIndex;

		public MergedRegion(int rowindex, int endRowIndex, int columnInde, int endColumnIndex){
			this.rowIndex = rowindex;
			this.endRowIndex = endRowIndex;
			this.columnIndex = columnInde;
			this.endColumnIndex = endColumnIndex;
		}
	}
	public static class Picture{
		public int rowIndex;
		public int columnIndex;
		public int endRowIndex;
		public int endColumnIndex;
		public byte[] data;

		public Picture(int rowindex, int endRowIndex, int columnInde, int endColumnIndex,byte[] data){
			this.rowIndex = rowindex;
			this.endRowIndex = endRowIndex;
			this.columnIndex = columnInde;
			this.endColumnIndex = endColumnIndex;
			this.data=data;
		}
	}

	public static class CellStyle {
		private int rowIndex;
		private int columnIndex;
//		private int endRowIndex;
//		private int endColumnIndex;
		private List<StyleType> stypeTypes;

		CellStyle() {
			stypeTypes = new ArrayList<>();
		}

		public CellStyle setlocation(int rowindex, int columnInde) {
			this.rowIndex = rowindex;
			this.columnIndex = columnInde;
			return (CellStyle) this;
		};

//		public CellStyle setMergedRegion(int rowindex, int endRowIndex, int columnInde, int endColumnIndex) {
//			this.rowIndex = rowindex;
//			this.endRowIndex = endRowIndex;
//			this.columnIndex = columnInde;
//			this.endColumnIndex = endColumnIndex;
//			this.stypeTypes.add(StyleType.MERGED_REGION);
//			return (CellStyle) this;
//		}

		private short fillForeGroundColor;
		private FillPatternType fillPattern;

		public CellStyle setFillColor(short fillForeGroundColor, FillPatternType fillPattern) {
			this.fillForeGroundColor = fillForeGroundColor;
			this.fillPattern = fillPattern;
			stypeTypes.add(StyleType.FILL_COLOR);
			return (CellStyle) this;
		}

		private BorderStyle borderBottom;
		private BorderStyle borderLeft;
		private BorderStyle borderTop;
		private BorderStyle borderRight;

		public CellStyle setBorder(BorderStyle borderBottom, BorderStyle borderLeft, BorderStyle borderTop,
                                   BorderStyle borderRight) {
			this.borderBottom = borderBottom;
			this.borderLeft = borderLeft;
			this.borderTop = borderTop;
			this.borderRight = borderRight;
			stypeTypes.add(StyleType.BORDER);
			return (CellStyle) this;
		}

		private short fontColor;
		private String fontName;
		private boolean boldWeight;
		private short fontHeightPoints;

		public CellStyle setFont(short fontColor, String fontName, boolean boldWeight, Short fontHeightPoints) {
			this.fontColor = fontColor;
			this.fontName = fontName;
			this.boldWeight = boldWeight;
			this.fontHeightPoints = fontHeightPoints;
			stypeTypes.add(StyleType.FONT);
			return (CellStyle) this;
		}

		private HorizontalAlignment alignment;

		public CellStyle setAlignment(HorizontalAlignment alignment) {
			this.alignment = alignment;
			stypeTypes.add(StyleType.ALIGNMENT);
			return (CellStyle) this;
		}

		public int getRowIndex() {
			return rowIndex;
		}

		public void setRowIndex(int rowIndex) {
			this.rowIndex = rowIndex;
		}

		public int getColumnIndex() {
			return columnIndex;
		}

		public void setColumnIndex(int columnIndex) {
			this.columnIndex = columnIndex;
		}

//		public int getEndRowIndex() {
//			return endRowIndex;
//		}
//
//		public void setEndRowIndex(int endRowIndex) {
//			this.endRowIndex = endRowIndex;
//		}
//
//		public int getEndColumnIndex() {
//			return endColumnIndex;
//		}
//
//		public void setEndColumnIndex(int endColumnIndex) {
//			this.endColumnIndex = endColumnIndex;
//		}

		public List<StyleType> getStypeTypes() {
			return stypeTypes;
		}

		public void setStypeTypes(List<StyleType> stypeTypes) {
			this.stypeTypes = stypeTypes;
		}

		public short getFillForeGroundColor() {
			return fillForeGroundColor;
		}

		public void setFillForeGroundColor(short fillForeGroundColor) {
			this.fillForeGroundColor = fillForeGroundColor;
		}

		public FillPatternType getFillPattern() {
			return fillPattern;
		}

		public void setFillPattern(FillPatternType fillPattern) {
			this.fillPattern = fillPattern;
		}

		public BorderStyle getBorderBottom() {
			return borderBottom;
		}

		public void setBorderBottom(BorderStyle borderBottom) {
			this.borderBottom = borderBottom;
		}

		public BorderStyle getBorderLeft() {
			return borderLeft;
		}

		public void setBorderLeft(BorderStyle borderLeft) {
			this.borderLeft = borderLeft;
		}

		public BorderStyle getBorderTop() {
			return borderTop;
		}

		public void setBorderTop(BorderStyle borderTop) {
			this.borderTop = borderTop;
		}

		public BorderStyle getBorderRight() {
			return borderRight;
		}

		public void setBorderRight(BorderStyle borderRight) {
			this.borderRight = borderRight;
		}

		public short getFontColor() {
			return fontColor;
		}

		public void setFontColor(short fontColor) {
			this.fontColor = fontColor;
		}

		public String getFontName() {
			return fontName;
		}

		public void setFontName(String fontName) {
			this.fontName = fontName;
		}

		public boolean isBoldWeight() {
			return boldWeight;
		}

		public void setBoldWeight(boolean boldWeight) {
			this.boldWeight = boldWeight;
		}

		public short getFontHeightPoints() {
			return fontHeightPoints;
		}

		public void setFontHeightPoints(short fontHeightPoints) {
			this.fontHeightPoints = fontHeightPoints;
		}

		public HorizontalAlignment getAlignment() {
			return alignment;
		}

		private int wcolumnWidth;
		private int wcolumnIndex;
		private int wrowIndex;

		public CellStyle setColumnWidth(int wcolumnIndex,int wcolumnWidth) {
			this.wcolumnWidth = wcolumnWidth;
			this.wcolumnIndex = wcolumnIndex;
			this.stypeTypes.add(StyleType.COLUMN_WIDTH);
			return (CellStyle) this;
		}
		public CellStyle setColumnWidthForRow(int wrowIndex,int wcolumnWidth) {
			this.wrowIndex=wrowIndex;
			this.stypeTypes.add(StyleType.COLUMN_WIDTH);
			return (CellStyle) this;
		}

		public int getWrowIndex() {
			return wrowIndex;
		}

		public void setWrowIndex(int wrowIndex) {
			this.wrowIndex = wrowIndex;
		}

		public int getWcolumnIndex() {
			return wcolumnIndex;
		}

		public void setWcolumnIndex(int wcolumnIndex) {
			this.wcolumnIndex = wcolumnIndex;
		}

	}

	public static String getCellValue(Cell cell){
		if(cell==null){
			return "";
		}
		switch (cell.getCellType())
		{
			case NUMERIC: return cell.getNumericCellValue()+"";
			case BOOLEAN: return cell.getBooleanCellValue()+"";
			case STRING: return cell.getStringCellValue();
			case FORMULA: return cell.getCellFormula();
			case BLANK: return "";
			default: return "";
		}
	}

	public static int[] findContentRowIndex(Sheet sheet,String content,boolean islike){
		if(content==null){
			return new int[]{-1,-1};
		}
		boolean find=false;
		for(int i=sheet.getFirstRowNum();i<=sheet.getLastRowNum();i++){
			Row row=sheet.getRow(i);
			for(int j=row.getFirstCellNum();j<=row.getLastCellNum();j++){
				String cellValue=ExcelOperation.getCellValue(row.getCell(j));
				if(cellValue==null){
					continue;
				}
				if(islike){
					if(cellValue.contains(content)){
						return new int[]{i,j};
					}
				}else{
					if(content.equals(cellValue)){
						return new int[]{i,j};
					}
				}
			}
		}
		return new int[]{-1,-1};
	}
}
